/*
    This file is part of QTau
    Copyright (C) 2013-2018  Tobias "Tomoko" Platen <tplaten@posteo.de>
    Copyright (C) 2013       digited       <https://github.com/digited>
    Copyright (C) 2010-2013  HAL@ShurabaP  <https://github.com/haruneko>

    QTau is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    SPDX-License-Identifier: GPL-3.0+
*/

#ifndef CONTROLLER_H
#define CONTROLLER_H

#include <QObject>
#include <QMap>
#include <QDir>
#include <QThread>
#include "Utils.h"

class MainWindow;
class qtauSynth;
class qtmmPlayer;
class qtauAudioSource;
class qtauSession;
class AudioEngine;
class JackAudio;
#include "PluginInterfaces.h"
#include "audio/outputbuffer.h"


// main class of QTau that ties everything together, also used in headless mode (TODO)
class qtauController : public QObject, public IController
{
    Q_OBJECT
public:
    explicit qtauController(QString dir,QObject *parent = 0);
    ~qtauController();
    void shutdown(int rc);//must be called before destoying the object

    bool run(); // app startup & setup, window creation
    ISynth* activeSynth(){return _activeSynth;}
    ISynth* selectedSynth(){return _selectedSynth;};
    static qtauController* instance();

    void startPlayback(float startPos);
    void stopPlayback();
    void selectSinger(QString singerName);
    void updateTempoTimeSignature(int tempo);
    int sampleRate();
    void startOfflinePlayback(const QString& fileName);
    QString lastPlay(){return _lastPlay;}



signals:

    void playStart();
    void playPause();
    void playStop();

    void playerSetVolume(int level);
    void transportPositionChanged(float pos);

public slots:
    void onLoadUST(QString fileName);
    void onSaveUST(QString fileName, bool rewrite);

    //void onRequestSynthesis();
    void onRequestStartPlayback();
    void onRequestStopPlayback();
    void onRequestResetPlayback();

    void pianoKeyPressed(int);
    void pianoKeyReleased(int);


private slots:
    void jackTimer();
    void outbuf_startPlayback();
    void outbuf_stopPlayback();
private:
    //void transportStarting();
    void addFileToRecentFiles(QString fileName);
    bool validateScore(const QJsonArray& ust);
protected:

    JackAudio* _jack=nullptr;
    AudioEngine* _audio=nullptr;
    OutputBuffer* _outbuf=nullptr;
    MainWindow *_mainWindow;

    qtauSession *_activeSession;
    //float _samplesToMeasures;

    bool setupTranslations();
    bool setupPlugins();
    bool setupVoicebanks();

    void initSynth(ISynth *s);
    void initPreviewSynth(IPreviewSynth* ps);
    QMap<QString, ISynth*> _synths;
    ISynth* _activeSynth;
    ISynth* _selectedSynth;
    int _nonzeroStart=0;

    QDir _pluginsDir;
    QString _prefix;
    QStringList _voices;



    //bool _synthrunning;

    bool _previewRunning=false;
    bool _localRequestStartPlayback=false;
    IPreviewSynth* _preview=nullptr;
    QString _lastPlay;


    float _lastNoteEnd=0;
    int _jackSampleRate=0;

    void newEmptySession();
    void logError(const QString& error);
    void logDebug(const QString& debug);
    void logSuccess(const QString& success);
    void addPluginAction(QAction *action);
public:
    const QStringList& voices(){return _voices;}
    void setJackTranportEnabled(bool enabled);
};

#endif // CONTROLLER_H
